package com.stars.easyms.datasource.interceptor;

import com.stars.easyms.base.interceptor.AbstractEasyMsMethodInterceptor;
import com.stars.easyms.datasource.exception.DataSourceInterceptorException;
import com.stars.easyms.datasource.mybatis.EasyMsMybatisMethodInvocation;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * <p>className: BaseEasyMsDatasourceMethodInterceptor</p>
 * <p>description: EasyMsDatasource基础方法拦截器</p>
 *
 * @author guoguifang
 * @version 1.7.0
 * @date 2020/11/21 11:46 上午
 */
public abstract class BaseEasyMsDatasourceMethodInterceptor extends AbstractEasyMsMethodInterceptor {

    @Override
    protected Object proceed(MethodInvocation methodInvocation) throws DataSourceInterceptorException {
        try {
            return super.proceed(methodInvocation);
        } catch (DataSourceInterceptorException e) {
            throw e;
        } catch (Throwable t) {
            Throwable throwable = t;
            while (throwable instanceof UndeclaredThrowableException
                    || (throwable != null && throwable.getCause() != null && throwable.getCause() != throwable)) {
                if (throwable instanceof DataSourceInterceptorException) {
                    throw (DataSourceInterceptorException) throwable;
                }
                if (throwable instanceof UndeclaredThrowableException) {
                    throwable = ((UndeclaredThrowableException) throwable).getUndeclaredThrowable();
                } else {
                    throwable = throwable.getCause();
                }
            }
            // 当throwable.getCause() == throwable时需要再次判断throwable的类型
            if (throwable instanceof DataSourceInterceptorException) {
                throw (DataSourceInterceptorException) throwable;
            }
            Method method = methodInvocation.getMethod();
            throw new DataSourceInterceptorException("Invocation '{}' method '{}' execute failure!",
                    method.getDeclaringClass().getName(), method.getName(), t);
        }
    }

    @Override
    protected Object intercept(MethodInvocation methodInvocation) throws Throwable {
        if (methodInvocation instanceof EasyMsMybatisMethodInvocation) {
            EasyMsMybatisMethodInvocation mybatisMethodInvocation = (EasyMsMybatisMethodInvocation) methodInvocation;
            return interceptMybatisMethod(mybatisMethodInvocation, mybatisMethodInvocation.getMapperInterface(),
                    mybatisMethodInvocation.getMethod());
        }
        return interceptMethod(methodInvocation);
    }

    protected Object interceptMybatisMethod(MethodInvocation methodInvocation, Class<?> mapperInterface, Method method)
            throws DataSourceInterceptorException {
        return proceed(methodInvocation);
    }

    protected Object interceptMethod(MethodInvocation methodInvocation) throws Throwable {
        return proceed(methodInvocation);
    }
}
